﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Windows.Forms;
using Microsoft.EnterpriseManagement.UI.WpfWizardFramework;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.Framework.Client;
using Microsoft.TeamFoundation.Framework.Common;
using Microsoft.TeamFoundation.WorkItemTracking.Client;

namespace ServiceManager.TFSIntegration
{
    public class TFSService
    {

        private static readonly Dictionary<Guid, string> collections = new Dictionary<Guid, string>();
        private static readonly Dictionary<Guid, Dictionary<int, string>> projectsbyCollection = new Dictionary<Guid, Dictionary<int, string>>();
        private static TfsConfigurationServer tfsServer = null;

        private static bool init;

        public static void Inititalize(string tfsURL)
        {
            TFSUrl = tfsURL;
            if(!init)
                BuildCollections();
        }


        public static string TFSUrl { get; set; }


        internal static bool CanConnect(string url)
        {
            try
            {
                tfsServer = TfsConfigurationServerFactory.GetConfigurationServer(new Uri(url), new UICredentialsProvider());
                tfsServer.Connect(ConnectOptions.None);
                tfsServer.EnsureAuthenticated();
                MessageBox.Show("Successsfully connected to " + url, "Connect to Team Foundation Server", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message, "Connect to Team Foundation Server", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return false;
            }
            return true;
        }

        internal static void BuildCollections()
        {
            // Load the tfs instance 
            collections.Clear();
            projectsbyCollection.Clear();

            tfsServer = TfsConfigurationServerFactory.GetConfigurationServer(TFSUri,new UICredentialsProvider());
            
            tfsServer.EnsureAuthenticated();
            
            var configurationServerNode = tfsServer.CatalogNode;

            var tpcNodes = configurationServerNode.QueryChildren(new Guid[] { CatalogResourceTypes.ProjectCollection },false,CatalogQueryOptions.None);

            foreach (var tpcNode in tpcNodes)
            {
                collections.Add(tpcNode.Resource.Identifier, tpcNode.Resource.DisplayName);
                var workItemStore = GetWorkItemStore(tpcNode);

                var projectDictionary = workItemStore.Projects.Cast<Project>().ToDictionary(project => project.Id, project => project.Name);
                projectsbyCollection.Add(tpcNode.Resource.Identifier,projectDictionary);

            }

            init = true;


        }

        private static Project GetProject(Guid collectionId,int projectId)
        {

            Debug.Assert(collectionId!=Guid.Empty);
            
            var configurationServerNode = tfsServer.CatalogNode;
            var tpcNodes = configurationServerNode.QueryChildren(new Guid[] {CatalogResourceTypes.ProjectCollection},
                                                                 false, CatalogQueryOptions.None);

            var tpcNode = tpcNodes.ToList().Find(T => T.Resource.Identifier == collectionId);
            if(tpcNode==null)
                throw  new InvalidOperationException("Could not retrieve project collection");

            var workItemStore = GetWorkItemStore(tpcNode);

            var project = workItemStore.Projects.Cast<Project>().ToList().Find(T => T.Id == projectId);
            if (project == null)
                throw new InvalidOperationException("Could not retrieve project");

            return project;

        }

        private static WorkItemStore GetWorkItemStore(CatalogNode tpcNode)
        {
            var tpcServiceDefinition = tpcNode.Resource.ServiceReferences["Location"];
            var configLocationService = tfsServer.GetService<ILocationService>();
            var tpcUri = new Uri(configLocationService.LocationForCurrentConnection(tpcServiceDefinition));
            var tpc = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(tpcUri);
            return (WorkItemStore)tpc.GetService(typeof(WorkItemStore));
        }

        private static Uri TFSUri
        {
            get
            {
                if (TFSUrl == null)
                    throw new InvalidOperationException("TFS Url was not set");

                return new Uri(TFSUrl);
            }
        }
        
        public static Dictionary<Guid, string> GetCollections()
        {
            // Load the tfs instance 
            return collections;

        }

        public static Dictionary<int,string> GetProjects(Guid collectionKey)
        {

            if (projectsbyCollection.ContainsKey(collectionKey))
                return projectsbyCollection[collectionKey] ;

            return null;

        }

        public static int CreateBug(TFSBugData bugData)
        {
            var project = GetProject(bugData.CollectionId, bugData.ProjectId);
            var bugWorkItemType = project.WorkItemTypes["Bug"];
            var workItem = bugWorkItemType.NewWorkItem();
            workItem.Fields["Title"].Value = bugData.Title;
            workItem.Fields["Repro Steps"].Value = bugData.Description;
            workItem.Save();

            return workItem.Id;
        }


    }
}